; DATE 12/07/83  17:20         last revision

	TITLE	'Set System Time v1.0'
; SETTIME.A86
; H. M. Van Tassell 120 Hill Hollow Road, Watchung, NJ 07060 201-755-5372
; A program to set the MP/M or CP/M Plus clock and print time on screen
; Intended to be run at system start-up.

; This program reads the Compupro System Support Clock but can
; be used with any similar clock. The hard part is the date conversion
; to Julian.

; This get time routine was first written to be included in the
; BIOS or XIOS to set system clock and keep time using a one sec tick
; interrupt from a timer or some other tick generator

; RASM86 SETTIME $SZPZ
; LINK86 SETTIME

; if you dont have RASM86 you may use ASM86 and GENCMD.


CR		equ	0Dh
LF		equ	0Ah

PORT_BASE	equ	050h
CLKCMD		equ	PORT_BASE + 10
CLKDATA		equ	PORT_BASE + 11

	
	CSEG

	call gettime		;read system support clock
	mov dx,offset ascii_str ;print time on the screen
	mov cl,9
	int 224
	mov dx,offset bin_str	;send time to system storage
	mov cl,104
	int 224
	mov cl,0		;quit
	mov dl,0
	int 224

;****************************************
;*					*
;*	Routine to get	time		*
;*					*
;****************************************
;-------
gettime:
;-------
;
; read time from system support clock and put into both
; a date string in ascii and the sysdata block
; the datestr can be used to print time on console
; 
	mov	si,0		;start reading at seconds
	mov	di,17		; into datestr
	call	rtwo
	mov	tod_sec,ah
;	cmp	ah,0		;is sec=0?
;	jne	get_exit
;	call	rtwo
;	mov	tod_min,ah
;	cmp	ah,0		;is min=0?
;	jne	get_exit
;	call	rtwo
;	mov	tod_hr,ah
;	cmp	ah,0		;if hr=0 it's midnite
;	jne	get_exit
;
; get date into date string and convert calender
; date to julian date (1/1/78)
;
set_date:
	mov	si,2		;ptr to min in digtab
	mov	di,14		;ptr to min in datestr
	call	rtwo		;set min & hr for init. call
	mov	tod_min,ah
	call	rtwo
	mov	tod_hr,ah
	dec	di		;skip over space
ctoj:	call	rtwo		;convert date to julian
	mov	bh,0		;get yr as bin in al
	mov	bl,al		;bx=year-1900
	mov	di,1		;point to month
	call	rtwo		;get month into al
	sub	al,3		;is month in mar-feb of "year"
	jnc	ctoj1
	add	al,12		;jan or feb become 10,11
	dec	bx		;...of prior year
ctoj1:	xor	ah,ah		;bx="year"
	push	ax		;ax="month",save it
	mov	ax,1461		;mult "year" by leap year cycle
	mul	bx		;bx*ax=[dx,ax]
	mov	cx,4		;divide by 4
	xor	dh,dh
	div	cx		;[dx,ax]/cx=ax (quotient)
	mov	bx,ax		;save quotient in bx
	pop	ax		;restore "month"
	push	bx		;save ("year"*1461)/4
	mov	bx,153		;mult "month" by 153
	mul	bx		;bx*ax=[dx,ax]
	inc	ax
	inc	ax		;add 2 to low order bits
	mov	cx,5		;divide by 5
	xor	dh,dh
	div	cx		;ax=("month"*153+2)/5
	pop	bx		;bx=("year"*1461)/4
	add	bx,ax		;add em
	mov	di,4		;point to days
	call	rtwo		;get days into al
	mov	ah,0
	add	ax,bx		;add days
	sub	ax,28429+1	;convert to 1/1/78
	mov	tod_day,ax	;stash it away
get_exit: ret

;
; get 2 bcd clock digits and update string
; and convert to binary & bcd time digits
;
rtwo:	call	rone		;get lo order digit in al
	mov	dl,al		;save it in reg dl
	add	al,'0'		;convert to ascii
	mov	datestr[di],al ;and put in buffer
	dec	di		;backup in string
	call	rone		;get hi order digit
	mov	dh,al		;save it in dh
	add	al,'0'
	mov	datestr[di],al
	dec di! dec di		;backup over sepr
	mov	al,dh		;recover hi digit
	mov	cl,10		;mult by 10
	mul	cl		;al=10*digit
	add	al,dl		;add lo digit
	mov	cl,4		;rotate hi order bcd
	rol	dh,cl		;...into hi nibble
	add	dh,dl		;and add low order bcd
	mov	ah,dh		;ah=bcd time digit
	ret			;al=binary time digit
;
; get a bcd clock digit into al
; enter: si  point to digtab
;
rone:	mov	al,digtab[si]		;get the digit number
	inc	si			;bump to next digit
	add	al,10h			;add read mask
	out	clkcmd,al	
	cmp	al,15h			;is it hours 10 digit
	in	al,clkdata
	jnz	rone9
	sub	al,08h			;yes-kill 24 hour bit
rone9:	and	al,0fh			;strip irrelevant bits
	ret				;al=bcd clock digit


	eject
	DSEG
;********************************
;*				*
;*	data for routine	*
;*				*
;********************************

bin_str		rs	0
tod_day		rw	1
tod_hr		rb	1
tod_min		rb	1
tod_sec		db	0

ascii_str	db	CR,LF
		db	'System time set '
datestr		db	'MM/DD/YY  '	 ;date string
timestr		db	'HH:MM:00'	 ;time string
		db	CR,LF,'$'

digtab	db	0,1,2,3,4,5,11,12,9,10,7,8
;		ss  mm  hh   yy   mm   dd

	end